package com.yihaodian.index.solr.ext;

import java.io.IOException;
import java.util.Map;

import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.SortField;
import org.apache.solr.common.SolrException;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.schema.ExternalFileField;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.FloatField;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieFloatField;
import org.apache.solr.search.QParser;

/**
 * Get value from an external memory data structure instead of index.
 * 
 * Similiar with ExternalFileField.
 * 
 * @see ExternalFileField
 * 
 * @author zhouhang
 * 
 */
public class ExternalMemField extends FieldType {
	private String indexName;
	private FieldType ftype;
	private String keyFieldName;
	private IndexSchema schema;
	private float defVal;

	@Override
	protected void init(IndexSchema schema, Map<String, String> args) {

		restrictProps(SORT_MISSING_FIRST | SORT_MISSING_LAST);

		// Get index name from field definition.
		indexName = args.remove("indexName");

		// valType has never been used for anything except to throw an error, so
		// make it optional since the
		// code (see getValueSource) gives you a MemFloatSource.
		String ftypeS = args.remove("valType");
		if (ftypeS != null) {
			ftype = schema.getFieldTypes().get(ftypeS);
			if (ftype != null && !(ftype instanceof FloatField)
					&& !(ftype instanceof TrieFloatField)) {
				throw new SolrException(
						SolrException.ErrorCode.SERVER_ERROR,
						"Only float and pfloat (Trie|Float)Field are currently supported as external field type.  Got "
								+ ftypeS);
			}
		}
		keyFieldName = args.remove("keyField");
		String defValS = args.remove("defVal");
		defVal = defValS == null ? 0 : Float.parseFloat(defValS);
		this.schema = schema;

	}

	@Override
	public void write(TextResponseWriter writer, String name, IndexableField f)
			throws IOException {
		throw new UnsupportedOperationException();
	}

	@Override
	public SortField getSortField(SchemaField field, boolean reverse) {
		MemFloatSource source = (MemFloatSource) getValueSource(field, schema.getResourceLoader().getDataDir()); 
		return 	source.getSortField(reverse);
	}

	@Override
	public ValueSource getValueSource(SchemaField field, QParser parser) {
		return getValueSource(field, parser.getReq().getCore().getDataDir());
	}

	public ValueSource getValueSource(SchemaField field, String dataDir) {
		MemDataProvider provider = MemDataManager.getDataProvider(indexName,
				field.getName(), dataDir);
		return provider.getSource(indexName, field, getKeyField(), defVal,
				dataDir);
	}

	// If no key field is defined, we use the unique key field
	private SchemaField getKeyField() {
		return keyFieldName == null ? schema.getUniqueKeyField() : schema
				.getField(keyFieldName);
	}
}
